package me.zhengjie.timing.plc;

import lombok.RequiredArgsConstructor;
import me.zhengjie.WcsReport.WcsReportService;
import me.zhengjie.agvSend.AgvSendService;
import me.zhengjie.pojo.dto.*;
import me.zhengjie.pojo.entity.*;
import me.zhengjie.pojo.vo.AgvTaskSubmitVo;
import me.zhengjie.pojo.vo.TestVo;
import me.zhengjie.sqlservice.*;
import me.zhengjie.tcp.CircleLibraryTCP;
import me.zhengjie.utility.state.MaterialStatus;
import me.zhengjie.utility.state.TaskStatus;
import me.zhengjie.utility.state.TaskType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

@Component
@RequiredArgsConstructor
public class CircleLibraryTiming {

    private static final Logger chainLine = LoggerFactory.getLogger("chainLine");

    private final IwsWareHouseService iwsWareHouseService;

    private final CircleLibraryTCP circleLibraryTCP;

    private final AgvSendService agvSendService;

    private final WcsInboundMissionService wcsInboundMissionService;

    private final IwsStoreOutsideService iwsSOutsideService;

    private final WcsReportService wcsReportService;

    private final NestingMiddleTableService nestingMiddleTableService;

    private final WcsLineBodyAbnormalService wcsLineBodyAbnormalService;

    @Transactional
//    @Scheduled(fixedDelay = 1000)
    public void circleLibrary() {

        IwsStoreOutside iwsSOutsides = iwsSOutsideService.selectCircleLibrary(TaskType.STORAGE_TYPE_ONE_FLOOR_NEW_CIRCLE_LIBRARY.getMessage(), 3);
        if (iwsSOutsides != null) {
            String id = iwsSOutsides.getId();
            String containerCode = iwsSOutsides.getContainerCode();
            //通知PLC到达储位
            boolean b3 = circleLibraryTCP.writeWithRetry(510, 1, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), 3);
            //通知PLC开始测高
            boolean b = circleLibraryTCP.writeWithRetry(512, 1, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), 3);
            if (b) {
                //获取读码状态
                Integer i = circleLibraryTCP.readHoldingRegisters(11, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                if (i == 1) {
                    //获取读码结果
                    String palletCode = circleLibraryTCP.readHoldingRegistersString(12, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                    //查询任务获取任务id
                    List<WcsInboundMission> wcsInboundMissionList = wcsInboundMissionService.selectContainerCodeUpdateDesc(palletCode);
//                        WcsInboundMission wcsInboundMission = wcsInboundMissionService.selectContainerCode(palletCode);
                    if (!wcsInboundMissionList.isEmpty()) {
                        WcsInboundMission wcsInboundMission = wcsInboundMissionList.get(0);
                        String inboundCode = wcsInboundMission.getInboundCode();

                        //检测高度
                        Integer tall = circleLibraryTCP.readHoldingRegisters(31, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                        if (tall == 2) {
                            //测高完成，获取测高结果
                            Integer tallResult = circleLibraryTCP.readHoldingRegisters(30, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus());
                            if (tallResult != 0 && tallResult != 4) {
                                //1.发送wms查看栈板是否已入库
                                InboundIsCodeExistDto inboundIsCodeExist = new InboundIsCodeExistDto();
                                inboundIsCodeExist.setContainerCode(palletCode);
                                inboundIsCodeExist.setNest(true);
                                boolean exist = wcsReportService.inboundIsCodeExist(inboundIsCodeExist);
                                if (exist) {
                                    circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_MATERIAL_EXIST.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                    circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                    //agv任务取消
                                    TaskCancelDto taskCancelDto = new TaskCancelDto();
                                    taskCancelDto.setRobotTaskCode(inboundCode);
                                    taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                    AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                    if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                        wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                        //釋放儲位
                                        iwsSOutsideService.updateStatus(id, containerCode, 1);
                                        WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                        wcsLineBodyAbnormal.setContainerCode(palletCode);
                                        wcsLineBodyAbnormal.setAbnormalInformation("容器编码已存在,重复入库");
                                        wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                        boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                        if (!b2) {
                                            chainLine.error("创建线条异常数据失败");
                                            throw new RuntimeException("创建线条异常数据失败");
                                        }
                                    }
                                } else {
                                    //2.查询嵌套信息是有嵌套
//                                        ReturnVo returnVo = wcsReportService.middleNestingData(palletCode);
                                    List<NestingMiddleTable> nestingMiddleTables = nestingMiddleTableService.selectContainerCode(palletCode);
                                    if (nestingMiddleTables.isEmpty()) {
                                        circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_NO.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                        circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                        //agv任务取消
                                        TaskCancelDto taskCancelDto = new TaskCancelDto();
                                        taskCancelDto.setRobotTaskCode(inboundCode);
                                        taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                        AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                        if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                            wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                            //釋放儲位
                                            iwsSOutsideService.updateStatus(id, containerCode, 1);
                                            WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                            wcsLineBodyAbnormal.setContainerCode(palletCode);
                                            wcsLineBodyAbnormal.setAbnormalInformation("未查询到嵌套信息");
                                            wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                            boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                            if (!b2) {
                                                chainLine.error("创建线条异常数据失败");
                                                throw new RuntimeException("创建线条异常数据失败");
                                            }
                                        }
                                    } else {
                                        //3.对比MES信息和WMS库存信息是否一致
                                        TestVo testVo = wcsReportService.wmsInventoryInformation(palletCode);
                                        if (testVo.getCode() != 200) {
                                            circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_WMS_INVENTORY_INFORMATION_NO.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                            circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                            //agv任务取消
                                            TaskCancelDto taskCancelDto = new TaskCancelDto();
                                            taskCancelDto.setRobotTaskCode(inboundCode);
                                            taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                            AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                            if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                                wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                                //釋放儲位
                                                iwsSOutsideService.updateStatus(id, containerCode, 1);
                                                WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                                wcsLineBodyAbnormal.setContainerCode(palletCode);
                                                wcsLineBodyAbnormal.setAbnormalInformation("WMS未找到载具码信息");
                                                wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                                boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                                if (!b2) {
                                                    chainLine.error("创建线条异常数据失败");
                                                    throw new RuntimeException("创建线条异常数据失败");
                                                }
                                            }
                                        } else {
                                            //对比库存信息 对比物料条码和数量
//                                                    ArrayList<MiddleTable> mesMiddleTableList = (ArrayList<MiddleTable>) returnVo.getData();
                                            List<MaterialDao> materialDaoList = testVo.getData();
                                            HashSet<InventoryContrast> mesInventorySet = new HashSet<>();
                                            HashSet<InventoryContrast> wmsInventorySet = new HashSet<>();
//                                                    BeanUtils.copyProperties(nestingMiddleTables,mesInventorySet);
//                                                    BeanUtils.copyProperties(wmsInventoryList,wmsInventorySet);
                                            for (MaterialDao datum : materialDaoList) {
                                                InventoryContrast wmsInventory = new InventoryContrast();
                                                BeanUtils.copyProperties(datum, wmsInventory);
                                                wmsInventorySet.add(wmsInventory);
                                            }
                                            for (NestingMiddleTable middleTable : nestingMiddleTables) {
                                                InventoryContrast wmsInventory = new InventoryContrast();
                                                BeanUtils.copyProperties(middleTable, wmsInventory);
                                                mesInventorySet.add(wmsInventory);
                                            }
                                            if (!mesInventorySet.equals(wmsInventorySet)) {
                                                //WMS和WES库存信息不一致
                                                circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_MES_AND_WMS_INVENTORY_NO.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                //agv任务取消
                                                TaskCancelDto taskCancelDto = new TaskCancelDto();
                                                taskCancelDto.setRobotTaskCode(inboundCode);
                                                taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                                AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                                if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                                    wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                                    //釋放儲位
                                                    iwsSOutsideService.updateStatus(id, containerCode, 1);
                                                    WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                                    wcsLineBodyAbnormal.setContainerCode(palletCode);
                                                    wcsLineBodyAbnormal.setAbnormalInformation("WMS和WES库存信息不一致");
                                                    wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                                    boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                                    if (!b2) {
                                                        chainLine.error("创建线条异常数据失败");
                                                        throw new RuntimeException("创建线条异常数据失败");
                                                    }
                                                }
                                            } else {
                                                //库存信息一致，获取终点储位
                                                //3获取终点储位
                                                InboundStorageApplyDto1 inboundStorageApplyDto = new InboundStorageApplyDto1();
                                                inboundStorageApplyDto.setContainerCode(palletCode);
                                                inboundStorageApplyDto.setFloor(String.valueOf(TaskType.ONE_FLOOR.getMessage()));
                                                inboundStorageApplyDto.setNest(true);
                                                List<NestingMiddleTable> nestingMiddleTables1 = nestingMiddleTableService.selectContainerCode(palletCode);
                                                ArrayList<NestingMiddleTable> materialDaos = new ArrayList<>();
                                                for (NestingMiddleTable nestingMiddleTable : nestingMiddleTables1) {
                                                    NestingMiddleTable nestingMiddleTable1 = new NestingMiddleTable();
                                                    BeanUtils.copyProperties(nestingMiddleTable,nestingMiddleTable1);
                                                    materialDaos.add(nestingMiddleTable1);
                                                }
                                                inboundStorageApplyDto.setData(materialDaos);
//                                                inboundStorageApplyDto.setData(null);
                                                //发送WMS申请入库请求终点储位
                                                String destinationStorageCode = wcsReportService.inboundStorageApply(inboundStorageApplyDto);
                                                if (destinationStorageCode != null) {
                                                    //下发AGV继续执行任务指令
                                                    AGVTaskContinueExecuteDto agvTaskContinueExecuteDto = new AGVTaskContinueExecuteDto();
                                                    agvTaskContinueExecuteDto.setTriggerType("TASK");
                                                    agvTaskContinueExecuteDto.setTriggerCode(inboundCode);
                                                    ContinueExecute continueExecute = new ContinueExecute();
                                                    continueExecute.setSeq(0);
                                                    continueExecute.setType(TaskType.STORAGE.getMessage());
                                                    continueExecute.setCode(destinationStorageCode);
                                                    agvTaskContinueExecuteDto.setTargetRoute(continueExecute);
                                                    boolean b1 = agvSendService.taskContinueExecute(agvTaskContinueExecuteDto);
                                                    if (b1) {
                                                        //通知plc离开
                                                        circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_YES.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                        circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                        //修改任务终点
                                                        boolean b4 = wcsInboundMissionService.updateDestination(inboundCode, destinationStorageCode);
                                                        if (!b4) {
                                                            chainLine.error("修改1楼回库终点储位失败，数据库异常");
                                                            throw new RuntimeException("修改1楼回库终点储位失败，数据库异常");
                                                        }
                                                        //釋放儲位
                                                        iwsSOutsideService.updateStatus(id, null, 0);
                                                    }
                                                } else {
                                                    //终点储位申请失败，取消任务
                                                    circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), MaterialStatus.RETURN_ONE_RESULT_STORAGE_LOCATION_NOT_FOUND.getStatus(), MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                    circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                                                    //agv任务取消
                                                    TaskCancelDto taskCancelDto = new TaskCancelDto();
                                                    taskCancelDto.setRobotTaskCode(inboundCode);
                                                    taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                                    AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                                    if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                                        wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                                        //釋放儲位
                                                        iwsSOutsideService.updateStatus(id, containerCode, 1);
                                                        WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                                        wcsLineBodyAbnormal.setContainerCode(palletCode);
                                                        wcsLineBodyAbnormal.setAbnormalInformation("终点储位申请失败");
                                                        wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                                        boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                                        if (!b2) {
                                                            chainLine.error("创建线条异常数据失败");
                                                            throw new RuntimeException("创建线条异常数据失败");
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            } else if (tallResult == 4) {
                                //agv任务取消
                                TaskCancelDto taskCancelDto = new TaskCancelDto();
                                taskCancelDto.setRobotTaskCode(inboundCode);
                                taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                                AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                                if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                    wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                    //釋放儲位
                                    iwsSOutsideService.updateStatus(id, containerCode, 1);
                                }
                                WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                wcsLineBodyAbnormal.setContainerCode(palletCode);
                                wcsLineBodyAbnormal.setAbnormalInformation("测高结果超高");
                                wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                if (!b2) {
                                    chainLine.error("创建线条异常数据失败");
                                    throw new RuntimeException("创建线条异常数据失败");
                                }
                                //修改任务状态异常
                                //通知AGV解绑储位
//                                    CarrierUnbindDto carrierUnbindDto = new CarrierUnbindDto();
//                                    carrierUnbindDto.setSlotCategory(TaskType.SITE.getMessage());
//                                    carrierUnbindDto.setSlotCode(TaskType.ONE_FLOOR_RETURN_TO_STORAGE_LOCATION.getMessage());
//                                    carrierUnbindDto.setCarrierCategory("PALLET");
//                                    carrierUnbindDto.setCarrierType("1");
//                                    carrierUnbindDto.setInvoke(TaskType.UNBIND.getMessage());
//                                    agvSendService.carrierUnbind(carrierUnbindDto);
                            }
                        } else if (tall > 2) {
                            //测高状态异常，释放储位
                            //agv任务取消
                            TaskCancelDto taskCancelDto = new TaskCancelDto();
                            taskCancelDto.setRobotTaskCode(inboundCode);
                            taskCancelDto.setCancelType(TaskType.DROP.getMessage());
                            AgvTaskSubmitVo agvTaskSubmitVo = agvSendService.taskCancel(taskCancelDto);
                            if ("SUCCESS".equals(agvTaskSubmitVo.getCode())) {
                                wcsInboundMissionService.updateMissionStatus(inboundCode, TaskStatus.task_abnormal.getStatus());
                                //釋放儲位
                                iwsSOutsideService.updateStatus(id, containerCode, 1);
                                WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                                wcsLineBodyAbnormal.setContainerCode(palletCode);
                                wcsLineBodyAbnormal.setAbnormalInformation("测高状态异常");
                                wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                                boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                                if (!b2) {
                                    chainLine.error("创建线条异常数据失败");
                                    throw new RuntimeException("创建线条异常数据失败");
                                }
                            }
                        }
                    } else {
                        //返回失败
                        circleLibraryTCP.writeWithRetry(MaterialStatus.RETURN_TO_THE_WAREHOUSE_address.getStatus(), 4, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), 3);
                        circleLibraryTCP.writeWithRetry(MaterialStatus.AGV_LIKAI.getStatus(), 2, MaterialStatus.ONE_FLOOR_RETURN_TO_THE_WAREHOUSE.getStatus(), MaterialStatus.RETRY_COUNT.getStatus());
                        iwsSOutsideService.updateStatus(id, containerCode, 1);
                        WcsLineBodyAbnormal wcsLineBodyAbnormal = new WcsLineBodyAbnormal();
                        wcsLineBodyAbnormal.setContainerCode(palletCode);
                        wcsLineBodyAbnormal.setAbnormalInformation("未找到该栈板任务");
                        wcsLineBodyAbnormal.setCreateTime(LocalDateTime.now());
                        boolean b2 = wcsLineBodyAbnormalService.inertAbnormal(wcsLineBodyAbnormal);
                        if (!b2) {
                            chainLine.error("创建线条异常数据失败");
                            throw new RuntimeException("创建线条异常数据失败");
                        }
                    }
                } else if (i == 2 || i == 3) {
                    //讀碼失敗释放储位
//                        boolean b1 = iwsSOutsideService.updateStatus(id, null, 0);
                }
            }

        }
    }
}
